import xml.etree.ElementTree as ET
import lwpgt
import copy
import pygame

def indent(elem, level=0):
        """in-place prettyprint formatter"""
        i = "\n" + level*"  "
        if len(elem):
            if not elem.text or not elem.text.strip():
                elem.text = i + "  "
            if not elem.tail or not elem.tail.strip():
                elem.tail = i
            for elem in elem:
                indent(elem, level+1)
            if not elem.tail or not elem.tail.strip():
                elem.tail = i
        else:
            if level and (not elem.tail or not elem.tail.strip()):
                elem.tail = i

class Maps:
    def __init__(self,width=10, height=10, nrlayers=3):
        """init map"""
        #map width in tiles 32x32
        self.width=width
        #map height in tiles 32x32
        self.height=height
        #map layers
        self.maplayers=[]
        #tiles for map
        self.tiles=[]
        self.CreateBlankMap(self.width, self.height, nrlayers)
    
    def SetTile(self, posx, posy, layerID, tile):
        """set tile on position posx,posy at given layer"""
        self.maplayers[layerID].SetTile(posx, posy, tile)
    
    def GetTile(self, posx, posy, layerID):
        """get tile from position posx,posy on layerID"""
        return self.maplayers[layerID].GetTile(posx, posy)
    
    def AddLayer(self, layer):
        """add layer to the map"""
        self.maplayers.append(layer)

    def RemoveLayer(self, layer):
        """remove layer from map"""
        if layer in self.maplayers:
            self.maplayers.remove(layer)
    
    def Render(self, surface, camera, drawposition=(0, 0)):
        sur=pygame.Surface((camera.rect.w, camera.rect.h))
        sur.set_colorkey((255, 0, 255))
        sur.fill((255, 0, 255))
        """render map on given surface"""
        for l in self.maplayers:
            for y in range(self.height):
                for x in range(self.width):
                    #get object from map
                    tile=l.GetTile(x, y)
                    #if there is a Entity on the map
                    if tile!=None:
                        tile.Draw(sur, (x*32-camera.rect.x, y*32-camera.rect.y))
        surface.blit(sur, (0, 0))
    
    def GetMapCoordinates(self, screencoordinates, camera):
        """get map coordinates from screen coordinates\n
        you can use for getting tile coord under cursor by giving mouse position and camera object"""
        wrong=False
        tx=(screencoordinates[0]+camera.rect.x)/32
        ty=(screencoordinates[1]+camera.rect.y)/32
        if tx<0 or tx>self.width-1 or ty<0 or ty>self.height-1:wrong=True
        if wrong:
            return None
        else: return (int(tx), int(ty))
    
    def CreateBlankMap(self, width, height, nrlayers):
        """create blank map 
        width,height - size of the map
        nrlayers - number of layers """
        self.maplayers=[]
        for ll in range(nrlayers):
            layer=lwpgt.render2d.Layer(width, height)
            self.maplayers.append(layer)
    
    def LoadMapFromXML(self, filename, tiles):
        """
        load map from xml file 
        filename-name of file to load
        tiles-list contains all tiles sorted by ID 
        """
        try:
            tree=ET.parse(filename)
        except:
            print "cannot load file or map file corrupted", filename
        else:
            self.maplayers=[]
            #getting all layers
            layerselements=tree.findall("LAYER")
            #in each layer
            for layer in layerselements:
                #create empty layer
                newlayer=lwpgt.render2d.Layer(int(layer.get("width")), int(layer.get("height")))
                #getting all tiles
                objectelements=layer.findall("tile")
                #in each tile in the layer
                for obj in objectelements:
                    #setting tile at the layer
                    newlayer.SetTile(int(obj.get("x")), int(obj.get("y")), tiles[int(obj.get("ID"))])
                #adding layer to map
                self.maplayers.append(newlayer)
    
    def  SaveMapToXML(self, filename, tiles):
        """save map to XML file
        filename - filename to load from
        tiles - list of tiles sorted by ID """
        #create main Node MAP
        mainnode=ET.Element("MAP")
        #in each layer
        for layer in self.maplayers:
            #make layer node LAYER
            layernode=ET.Element("LAYER")
            layernode.set("width", str(self.width))
            layernode.set("height", str(self.height))
            
            for yy in range(self.height):
                for xx in range(self.width):
                    tile=layer.GetTile(xx, yy)
                    if tile!=None:
                        #create tile node 
                        tilenode=ET.Element("tile")
                        tilenode.set("x", str(xx))
                        tilenode.set("y", str(yy))
                        tilenode.set("ID", str(tiles.index(tile)))
                        #append tile node to  layer node
                        layernode.append(tilenode)
            #append layer node to main node
            mainnode.append(layernode)
        #indent root
        indent(mainnode)
        #make tree
        maintree=ET.ElementTree(mainnode)
        #write it to file
        maintree.write(filename)
        print "Map Saved as", filename
